Collections And Enumerables

Rapid overview

🧠 📚 Collection Interfaces — Deep Dive with Examples

---

---

Questions & Answers

Q: Why should I return IEnumerable instead of List?

A: IEnumerable exposes only iteration, hiding mutability and implementation details. Callers can't modify the source, and you can swap concrete types (arrays, lists, query results) without breaking contracts.

Q: When should I use ICollection over IEnumerable?

A: When you need Count without enumerating everything, or when callers need Add/Remove. Trading systems use ICollection for position snapshots where count matters for validation.

Q: What's the performance difference between IEnumerable and IList?

A: IList supports O(1) indexed access; IEnumerable is forward-only. Use IList when random access is needed; otherwise prefer IEnumerable for flexibility and deferred execution.

Q: How does IQueryable enable LINQ-to-SQL?

A: IQueryable builds expression trees instead of executing code. Providers like Entity Framework translate these trees into SQL, pushing filtering/sorting to the database instead of memory.

Q: Should I return IReadOnlyCollection or IEnumerable?

A: IReadOnlyCollection when Count is cheap and useful to callers (e.g., pre-allocated arrays). IEnumerable when iteration might be lazy or infinite, or when hiding collection semantics.

Q: What happens if I call .ToList() on every IEnumerable?

A: You materialize the entire sequence into memory immediately, losing lazy evaluation benefits. This hurts performance with large datasets and breaks streaming scenarios.

Q: How do these interfaces relate to LINQ?

A: LINQ methods extend IEnumerable and IQueryable. IEnumerable uses LINQ-to-Objects (in-memory), IQueryable uses providers (LINQ-to-SQL, LINQ-to-Entities) for remote execution.

Q: Can I cast IEnumerable to List safely?

A: Not always. Use source as List<T> for null-safe casting, but prefer enumeration. Casting breaks abstraction and assumes implementation details callers shouldn't know.

Q: How do collection interfaces improve testability?

A: Accepting IEnumerable lets tests pass arrays, lists, or mock sequences. Returning interfaces enables stub implementations, avoiding heavyweight setup.

Q: What's the memory impact of yielding with IEnumerable?

A: Iterator blocks (yield return) create state machines that produce items on demand, reducing peak memory. This is critical for processing large datasets or infinite sequences.